package busterminal.command.route;

import busterminal.command.AbstractCommand;
import busterminal.entity.Route;
import busterminal.entity.RouteImplementation;
import busterminal.entity.StoppingPoint;
import busterminal.entity.service.RouteType;
import busterminal.exception.BusinessException;
import busterminal.persistence.RouteDAO;
import busterminal.persistence.StoppingPointDAO;
import busterminal.services.ServiceLocator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Класс, реализуюий действие: создание нового маршрута
 */
public class CreateRouteCommand extends AbstractCommand {

    /**
     * Имя параметра "Номер маршрута"
     */
    public final static String PARAM_ROUTE_NUMBER = "Route number";
    /**
     * Имя параметра "Название маршрута"
     */
    public final static String PARAM_ROUTE_NAME = "Route name";
    /**
     * Имя параметра "Идентификатор начала маршрута"
     */
    public final static String PARAM_START_STOPPING_POINT_ID = "Start stopping point id";
    /**
     * Имя параметра "Идентификатор конца маршрута"
     */
    public final static String PARAM_END_STOPPING_POINT_ID = "End stopping point id";
    /**
     * Имя параметра "Список промежуточных остановочных пунктов"
     */
    public final static String PARAM_INTERMEDIATE_STOPPING_POINT_LIST = "Intermediate stopping point list (separated by comma)";
    /**
     * Имя параметра "Тип маршрута"
     */
    public final static String PARAM_ROUTE_TYPE = "Route type";
    /**
     * Разделитель для ввода промежуточных значений
     */
    private final static String SEPARATOR = " *[,] *";

    /**
     * Конструктор по умолчанию
     */
    public CreateRouteCommand() {
        super("Add new route");
    }

    /**
     * Выполнить команду: создать новый маршрут
     */
    @Override
    public void execute() {
        Route route = new RouteImplementation();

        route.setRouteNumber(parameters.get(PARAM_ROUTE_NUMBER));

        route.setRouteName(parameters.get(PARAM_ROUTE_NAME));

        String parameterStartStoppingPointId = parameters.get(PARAM_START_STOPPING_POINT_ID);
        int ID;
        try {
            ID = Integer.parseInt(parameterStartStoppingPointId);
        } catch (Exception e) {
            throw new BusinessException("Invalid start stopping point ID='" + parameterStartStoppingPointId + "';" + e.toString(), e);
        }

        StoppingPoint startStoppingPoint = ServiceLocator.getService(StoppingPointDAO.class).read(ID);
        if (startStoppingPoint == null) {
            throw new  BusinessException("Cannot find stopping point with id='" + ID + "'");
        }
        route.setStartPoint(startStoppingPoint);

        String parametrEndStoppingPointId = parameters.get(PARAM_END_STOPPING_POINT_ID);
        try {
            ID = Integer.parseInt(parametrEndStoppingPointId);
        } catch (Exception e) {
            throw new BusinessException("Invalid end stopping point ID='" + parametrEndStoppingPointId + "';" + e.toString(), e);
        }

        StoppingPoint endStoppingPoint = ServiceLocator.getService(StoppingPointDAO.class).read(ID);
        if (endStoppingPoint == null) {
            throw new  BusinessException("Cannot find stopping point with id='" + ID + "'");
        }
        route.setEndPoint(endStoppingPoint);

        List<String> stoppingPoints = Arrays.asList(parameters.get(PARAM_INTERMEDIATE_STOPPING_POINT_LIST).split(SEPARATOR));
        ArrayList<StoppingPoint> points = new ArrayList<StoppingPoint>();
        int stoppingPointId;
        for (String stoppingPoint : stoppingPoints) {
            try {
                stoppingPointId = Integer.parseInt(stoppingPoint);
            } catch (Exception e) {
                throw new BusinessException("Invalid intermediate stopping point ID='" + stoppingPoint + "';" + e.toString(), e);
            }
            StoppingPoint intermediateStoppingPoint = ServiceLocator.getService(StoppingPointDAO.class).read(stoppingPointId);
            if (intermediateStoppingPoint == null) {
                throw new  BusinessException("Cannot find stopping point with id='" + stoppingPointId + "'");
            }
            points.add(intermediateStoppingPoint);
        }
        route.setIntermediateStoppingPointsList(points);

        String routeType = parameters.get(PARAM_ROUTE_TYPE);
        try {
            route.setRouteType(RouteType.valueOf(routeType.toUpperCase()));
        } catch (Exception e) {
            System.err.println("Incorrect route type " + routeType);
        }


        RouteDAO routeDAO = ServiceLocator.getService(RouteDAO.class);
        routeDAO.create(route);
    }

    /**
     * Получить список имён параметров
     * @return список имён параметров
     */
    @Override
    public List<String> getParametersNames() {
        return Arrays.asList(PARAM_ROUTE_NUMBER, PARAM_ROUTE_NAME, PARAM_START_STOPPING_POINT_ID, PARAM_END_STOPPING_POINT_ID, PARAM_INTERMEDIATE_STOPPING_POINT_LIST, PARAM_ROUTE_TYPE);
    }

    /**
     * Вывести список доступных вариантов параметра с фиксированным набором значений
     * @param parameterName имя параметра с фиксированным набором значений
     */
    @Override
    public void showAccessableVariants(String parameterName) {
        if (PARAM_ROUTE_TYPE.equals(parameterName)) {
            System.out.println("Accessable variants: " + RouteType.getValues());
        }
    }

}
